/**
 * JAVACC DEMO 1.0
 */
package com.apache.rpc.client;

import com.apache.api.vo.ResultEntity;
import com.apache.exception.ServiceException;
import com.apache.tools.StrUtil;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.log4j.Logger;

import java.io.InputStream;
import java.util.Map;

/**
 * description:  http通信接口实现
 *
 * @author Hou Dayu 创建时间：2016-10-28
 */
public class HttpProtocolService extends AbstractProtocolService {

    private Logger logger = Logger.getLogger(HttpProtocolService.class);

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     */
    public ResultEntity doService(String beanId, String methodKey, Map<String, Object> params) {
        String paramType = StrUtil.doNull(String.valueOf(params.get("ParamType")), "xml");//返报文类型
        String xmlParams = this.buildXml(beanId, methodKey, "http", params);
        ResultEntity resultEntity = null;
        if (null == register) {
            resultEntity = getResultEntity("没有发布待执行的接口信息");
            return resultEntity;
        }
        String httpUrl = register.getAddress();
        try {
            String result = postHttp(httpUrl, xmlParams, paramType);
            String rows = StrUtil.doNull(String.valueOf(params.get("pageSize")),
                    String.valueOf(params.get("rows")));
            resultEntity = this.getResultEntity(result, paramType, rows);
        } catch (ServiceException e) {
            resultEntity = getResultEntity(e.getMessage());
        }
        return resultEntity;
    }

    public String doServiceStr(String beanId, String methodKey, Map<String, Object> params) {
        String paramType = StrUtil.doNull(String.valueOf(params.get("ParamType")), "xml");
        String xmlParams = this.buildXml(beanId, methodKey, "http", params);
        if (null == register) {
            return "";
        }
        String httpUrl = register.getAddress();
        try {
            return postHttp(httpUrl, xmlParams, paramType);
        } catch (ServiceException e) {
            return "";
        }
    }

    /**
     * post http 请求，接受返回的结果xml文档
     *
     * @param url webservice地址
     * @return xml类型字符串
     */
    private String postHttp(String url, String params, String type) {
        PostMethod postMethod = null;
        InputStream inputStream = null;
        try {
            HttpClient client = new HttpClient();
            client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
            if(this.isSendBody()){
                postMethod = new PostMethod(url+"?httpRand="+ System.currentTimeMillis()+"&ParamType="+ type);
                postMethod.setRequestEntity(new StringRequestEntity(params,"application/xml","UTF-8"));
            }else {
                postMethod = new PostMethod(url);
                //重新构造参数数组，是为了加入公共参数：随机数，以防缓存影响执行结果
                NameValuePair[] paras = new NameValuePair[3];
                paras[0] = new NameValuePair("httpRand", "" + System.currentTimeMillis());
                paras[1] = new NameValuePair("params", "" + params);
                paras[2] = new NameValuePair("ParamType", "" + type);
                postMethod.setRequestBody(paras);//绑定参数
            }
            logger.info("HTTP请求发送成功");
            int statusCode = client.executeMethod(postMethod);
            logger.info("服务端返回请求状态，状态码为：" + statusCode);
            if (statusCode == HttpStatus.SC_OK) {//如果执行成功
                inputStream = postMethod.getResponseBodyAsStream();
                String line = IOUtils.toString(inputStream, "UTF-8");
                return line;
            } else {
                logger.error("HTTP请求响应失败，错误码为[" + statusCode+"]，请求地址["+url+"]");
            }
        } catch (Exception e) {
            logger.error(e);
        } finally {
            IOUtils.closeQuietly(inputStream);
            if (null != postMethod)
                postMethod.releaseConnection();//释放连接
        }
        return "";
    }
}
